#pragma once

constexpr const char* ModelFragmentShader_Src =
"#version 330 compatibility\n"
"layout(location = 0) out vec3 color;\n"
"\n"
"in vec3 vertColorFrag;\n"
"in vec3 vertFragPos;\n"
"in vec3 vertNormal;\n"
"in vec2 vertUVLayer;\n"
"\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"\n"
"uniform int diffuseLoaded;\n"
"uniform sampler2D diffuseTexture;\n"
"uniform sampler2D normalTexture;\n"
"uniform sampler2D glossTexture;\n"
"uniform sampler2D specularTexture;\n"
"\n"
"// http://www.thetenthplanet.de/archives/1180\n"
"mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv)\n"
"{\n"
"  // get edge vectors of the pixel triangle\n"
"  vec3 dp1 = dFdx(p);\n"
"  vec3 dp2 = dFdy(p);\n"
"  vec2 duv1 = dFdx(uv);\n"
"  vec2 duv2 = dFdy(uv);\n"
"\n"
"  // solve the linear system\n"
"  vec3 dp2perp = cross(dp2, N);\n"
"  vec3 dp1perp = cross(N, dp1);\n"
"  vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;\n"
"  vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;\n"
"\n"
"  // construct a scale-invariant frame \n"
"  float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );\n"
"  return mat3(T * invmax, B * invmax, N);\n"
"}\n"
"\n"
"vec3 perturb_normal(vec3 N, vec3 V, vec2 texcoord)\n"
"{\n"
"  // assume N, the interpolated vertex normal and \n"
"  // V, the view vector (vertex to eye)\n"
"  vec3 map = normalize(texture(normalTexture, texcoord).rgb * -2 + 1);\n"
"  // not deriving z for now\n"
"  mat3 TBN = cotangent_frame(N, V, texcoord);\n"
"  return normalize(TBN * map);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
"  // Ambient\n"
"  float ambientStrength = 0.1;\n"
"  vec3 ambient = ambientStrength * vec3(1, 1, 1);  // Amb color\n"
"\n"
"  vec3 viewPos = inverse(view)[3].xyz;\n"
"  vec3 viewDir = normalize(viewPos - vertFragPos);\n"
"  \n"
"  vec3 norm = normalize(vertNormal);\n"
"  if (diffuseLoaded == 1) {\n"
"    norm = perturb_normal(norm, viewDir, vertUVLayer);\n"
"  }\n"
"\n"
"  // Diffuse\n"
"  vec3 lightDir = normalize(inverse(view)[3].xyz - vertFragPos);\n"
"  float diff = max(dot(norm, lightDir), 0.0);\n"
"  vec3 diffuse = diff * texture(diffuseTexture, vertUVLayer).rgb;  // Light color\n"
"\n"
"  // Specular\n"
"  vec3 reflectDir = reflect(-lightDir, norm);\n"
"  \n"
"  float gloss = texture(glossTexture,vertUVLayer).r;\n"
"  float spec = pow(max(dot(viewDir, reflectDir), 0.0), 2);\n"
"  vec3 specular = texture(specularTexture, vertUVLayer).rgb * spec * gloss;\n"
"  \n"
"  // Result\n"
"  if (diffuseLoaded == 1) {\n"
"    color = (ambient + diffuse + specular);\n"
"  } else {\n"
"    color = vec3(diff);\n"
"  }\n"
"}";